package com.laicunba.service.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.dao.GenericQueryDao;
import com.laicunba.pojo.FinancingTargetBidDO;
import com.laicunba.pojo.param.Page;
import com.laicunba.pojo.vo.CPBBidGroupVO;
import com.laicunba.pojo.vo.CPBBidVO;
import com.laicunba.pojo.vo.FinancingTargetBidVO;
import com.laicunba.pojo.vo.SCBGroupVO;
import com.laicunba.service.FinancingTargetBidService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.DateUtil;
import com.laicunba.util.StringUtil;

@SuppressWarnings({ "unchecked", "rawtypes" })
@Service
public class FinancingTargetBidServiceImpl extends BaseServiceImpl implements FinancingTargetBidService {

	@Autowired
	private GenericQueryDao queryDao;

	@Override
	public List<FinancingTargetBidDO> findByCertificateId(String certificateId) {
		return queryDao.selectList("FINANCING_TARGET_BID.findByCertificateId", certificateId);
	}

	@Override
	public List<FinancingTargetBidVO> findByFinancingTargetId(String financingTargetId) {
		return queryDao.selectList("FINANCING_TARGET_BID.findByFinancingTargetId", financingTargetId);
	}

	@Override
	public List<FinancingTargetBidVO> findLast(int rows) {
		return queryDao.selectList("FINANCING_TARGET_BID.findLast", rows);
	}

	@Override
	public FinancingTargetBidDO findOneByCertificateId(String certificateId) {
		List<FinancingTargetBidDO> list = findByCertificateId(certificateId);
		if (list == null || list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	@Override
	public List<FinancingTargetBidDO> findWithdrawAble(String userId, String type) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("type", type);
		return queryDao.selectList("FINANCING_TARGET_BID.findWithdrawAble", map);
	}

	@Override
	public boolean subtractAmount(String id, BigDecimal subtractPrincipal, BigDecimal subtractProfit) {
		Map map = new HashMap();
		map.put("id", id);
		map.put("subtractPrincipal", subtractPrincipal);
		map.put("subtractProfit", subtractProfit);
		return updateDao.update("FINANCING_TARGET_BID.subtractAmount", map) == 1;
	}
	
	@Override
	public int countByFinancingTargetId(String financingTargetId) {
		return queryDao.selectOne("FINANCING_TARGET_BID.countFinancingTargetId", financingTargetId);
	}

	@Override
	public List<FinancingTargetBidVO> findByFinancingTargetIdWithLimit(String financingTargetId, Page page) {
		Map map = new HashMap();
		map.put("financingTargetId", financingTargetId);
		if(page != null && page.getPageIndex() > 0) {
			map.put("limit", page.getPageSize());
			map.put("offset", (page.getPageIndex() - 1) * page.getPageSize());
		}
		return queryDao.selectList("FINANCING_TARGET_BID.findByFinancingTargetIdWithLimit", map);
	}

	@Override
	public List<CPBBidGroupVO> findCPBGroup(String userId) {
		return queryDao.selectList("FINANCING_TARGET_BID.findCPBGroup", userId);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public List<CPBBidVO> findCPBVO(String userId, String financingTargetId) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("financingTargetId", financingTargetId);
		return queryDao.selectList("FINANCING_TARGET_BID.findCPBVO", map);
	}

	@Override
	public SCBGroupVO findSCBGroup(String userId) {
		return queryDao.selectOne("FINANCING_TARGET_BID.findSCBGroup", userId);
	}

	@Override
	public boolean isFirstBid(String bidUserId) {
		return ((Integer) queryDao.selectOne("FINANCING_TARGET_BID.getBidCount", bidUserId) == 1);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public BigDecimal countProfit(String userId, String withdrawType) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("withdrawType", withdrawType);
		return queryDao.selectOne("FINANCING_TARGET_BID.countProfit", map);
	}

	@Override
	public List<FinancingTargetBidDO> findRewardBid(String userId) {
		return queryDao.selectList("FINANCING_TARGET_BID.findRewardBid", userId);
	}

	@Override
	public BigDecimal countRewardProfit(String userId) {
		return queryDao.selectOne("FINANCING_TARGET_BID.countRewardProfit", userId);
	}

	@Override
	public int countActivityTarget(String userId, String targetId, String channel) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userId", userId);
		map.put("targetId", targetId);
		map.put("channel", channel);
		return (Integer) queryDao.selectOne("FINANCING_TARGET_BID.countActivityTarget", map);
	}

	private static final MathContext mc = new MathContext(10, RoundingMode.HALF_DOWN);

	@Override
	public BigDecimal countRemainProfit(FinancingTargetBidDO bidDO) {

		if (bidDO.getWithdrawPrincipal() == null) {
			bidDO.setWithdrawPrincipal(BigDecimal.ZERO);
		}
		if (bidDO.getDeductionProfit() == null) {
			bidDO.setDeductionProfit(BigDecimal.ZERO);
		}
		if (bidDO.getBeginProfit() == null) {
			return BigDecimal.ZERO;
		}
		Date now = new Date();
		int days = DateUtil.days(bidDO.getBeginProfit(), now.after(bidDO.getEndProfit()) ? bidDO.getEndProfit() : now);
		if (days == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal profit = bidDO.getBuyAmount();// .subtract(bidDO.getWithdrawPrincipal());
		profit = profit.multiply(bidDO.getAnnualizedRates().divide(BigDecimal.valueOf(36500), mc));
		profit = profit.multiply(BigDecimal.valueOf(days));
		profit = profit.subtract(bidDO.getDeductionProfit());
		profit = profit.add(bidDO.getExpireSendProfit()!=null?bidDO.getExpireSendProfit():BigDecimal.ZERO);
		return profit;
	}

	@Override
	public List<FinancingTargetBidDO> findUpcomingActivityBids(int limit) {
		return queryDao.selectList("FINANCING_TARGET_BID.findUpcomingActivityBids", limit);
	}

	@Override
	public List<FinancingTargetBidVO> findFinancingTargetBidVOList(String userId, String beginTimeStr, String endTimeStr, String targetNameStr, String timeTypeStr, String borrowerId) {
		Map<String, Object> param = new HashMap<String, Object>();
		DateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
		beginTimeStr = StringUtil.isNotEmpty(beginTimeStr) ? beginTimeStr : sdf.format(new Date()) + " 00:00:00";
		endTimeStr = StringUtil.isNotEmpty(endTimeStr) ? endTimeStr : sdf.format(new Date()) + " 23:59:59";
		param.put("userId", userId);
		param.put("beginTimeStr", beginTimeStr);
		param.put("endTimeStr", endTimeStr);
		param.put("timeTypeStr", timeTypeStr);
		param.put("targetNameStr", targetNameStr);
		param.put("borrowerId", borrowerId);
		return queryDao.selectList("FINANCING_TARGET_BID.findFinancingTargetBidVOList", param);
	}

	@Override
	public List<FinancingTargetBidDO> findUpcomingFixBids(int limit) {
		return queryDao.selectList("FINANCING_TARGET_BID.findUpcomingFixBids", limit);
	}

	@Override
	public BigDecimal countActivityProfit(String userId) {
		return queryDao.selectOne("FINANCING_TARGET_BID.countActivityProfit", userId);
	}

	@Override
	public int countFixBidRows(String userId) {
		return queryDao.selectOne("FINANCING_TARGET_BID.countFixBidRows", userId);
	}

	@Override
	public boolean addCashCouponAmount(String id, BigDecimal amount) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("id", id);
		param.put("amount", amount);
		return updateDao.update("FINANCING_TARGET_BID.addCashCouponAmount", param) == 1;
	}

	@Override
	public List<CPBBidGroupVO> findExpireFixBidGroup(String userId) {
		return queryDao.selectList("FINANCING_TARGET_BID.findExpireFixBidGroup", userId);
	}

	@Override
	public List<CPBBidGroupVO> findNoExpireFixBidGroup(String userId) {
		return queryDao.selectList("FINANCING_TARGET_BID.findNoExpireFixBidGroup", userId);
	}

	@Override
	public List<CPBBidVO> findAllFixBidVO(String userId, String targetId) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("financingTargetId", targetId);
		return queryDao.selectList("FINANCING_TARGET_BID.findAllFixBidVO", map);
	}
	
	@Override
	public List<CPBBidVO> findExpireFixBidVO(String userId, String targetId) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("financingTargetId", targetId);
		return queryDao.selectList("FINANCING_TARGET_BID.findExpireFixBidVO", map);
	}

	@Override
	public List<CPBBidVO> findNoExpireFixBidVO(String userId, String targetId) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("financingTargetId", targetId);
		return queryDao.selectList("FINANCING_TARGET_BID.findNoExpireFixBidVO", map);
	}

	@Override
	public List<FinancingTargetBidDO> findListBidFromUserId(String userId, String payTimeStr1, String payTimeStr2, String endProfitTimeStr1, String endProfitTimeStr2) {
		Map map = new HashMap();
		map.put("userId", userId);
		map.put("payTimeStr1", payTimeStr1);
		map.put("payTimeStr2", payTimeStr2);
		map.put("endProfitTimeStr1", endProfitTimeStr1);
		map.put("endProfitTimeStr2", endProfitTimeStr2);
		return queryDao.selectList("FINANCING_TARGET_BID.findListBidFromUserId", map);
	}

	@SuppressWarnings("unchecked")
	@Transactional
	@Override
	public boolean updateFlagExpiredTransfer2Bank(String uid, String bidId) {
		Map map = new HashMap();
		map.put("uid", uid);
		map.put("bidId", bidId);
		AssertUtil.assertTrue(updateDao.update("FINANCING_TARGET_BID.updateFlagExpiredTransfer2Bank", map) == 1, "UPDATE_2BANK_FAIL");
		return true;
	}

	@Transactional
	@Override
	public boolean updateFlagExpiredTransfer2Current(String uid, String bidId) {
		Map map = new HashMap();
		map.put("uid", uid);
		map.put("bidId", bidId);
		AssertUtil.assertTrue(updateDao.update("FINANCING_TARGET_BID.updateFlagExpiredTransfer2Current", map) == 1, "UPDATE_2CURRENT_FAIL");
		return true;
	}

	@Override
	public boolean addRate(String id, BigDecimal rate) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("id", id);
		param.put("rate", rate);
		return updateDao.update("FINANCING_TARGET_BID.addRate", param) == 1;
	}

	@Transactional
	@Override
	public boolean updateSummary(String certificateId, String summary) {
		Map map = new HashMap();
		map.put("certificateId", certificateId);
		map.put("summary", summary);
		AssertUtil.assertTrue(updateDao.update("FINANCING_TARGET_BID.updateSummary", map) == 1, "UPDATE_BID_SUMMARY_FAIL");
		return true;
	}

	@Override
	public List<FinancingTargetBidVO> findReinvestBidList(String userId) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("userId", userId);
		return queryDao.selectList("FINANCING_TARGET_BID.findReinvestBidList", param);
	}

	@Override
	public int countFixBid2Demand(String userId) {
		return queryDao.selectOne("FINANCING_TARGET_BID.countFixBid2Demand", userId);
	}

	@Override
	public boolean frozen(String bid, String summary) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("bid", bid);
		param.put("summary", summary);
		return updateDao.update("FINANCING_TARGET_BID.frozen", param) == 1;
	}
	
	@Override
	public boolean deleteActivityBid(String bid) {
		return updateDao.update("FINANCING_TARGET_BID.deleteActivityBid", bid)==1;
	}
	 
	@Override
	public boolean updateExpireSendProfit(String bid, BigDecimal amount) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("id", bid);
		param.put("amount", amount);
		return updateDao.update("FINANCING_TARGET_BID.updateExpireSendProfit", param) == 1;
	}
	
	@Override
	public List<FinancingTargetBidDO> findUpcomingJzhFixBids(int limit) {
		return queryDao.selectList("FINANCING_TARGET_BID.findUpcomingJzhFixBids", limit);
	}
	
}
